﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassProxitator.Messages
{
    public abstract class Message
    {
        public abstract MessageType MessageType { get; }

        public abstract Task<byte[]> GetContentBytes();

        public abstract Task LoadIn(Stream s);

        public virtual async Task WriteTo(Stream stream)
        {
            var bytesTask = GetContentBytes().ConfigureAwait(false);
            await stream.WriteAsync((int)MessageType).ConfigureAwait(false);
            var bytes = await bytesTask;
            await stream.WriteAsync(bytes.Length).ConfigureAwait(false);
            await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
        }

        public static async Task<Message> Load(Stream s)
        {
            var type = (MessageType)await s.ReadInt32Async().ConfigureAwait(false);
            Message msg;
            switch (type)
            {
                case MessageType.MethodCall:
                    msg = new MethodCallMessage();
                    break;
                case MessageType.Result:
                    msg = new ResultMessage();
                    break;
                default: throw new NotSupportedException();
            }
            var bytesLength = await s.ReadInt32Async().ConfigureAwait(false);
            var bytes = new byte[bytesLength];
            await s.ReadAsync(bytes, 0, bytesLength).ConfigureAwait(false);
            using(var ms = new MemoryStream(bytes))
            {
                await msg.LoadIn(ms).ConfigureAwait(false);
            }
            return msg;
        }
    }
}
